using System.Diagnostics.CodeAnalysis;

namespace Guia.Win32
{
    using System.Drawing;
    using System.Runtime.InteropServices;

    /// <summary>
    /// Helper class to simulate mouse events.
    /// </summary>
    public static class MouseHelper
    {
        /// <summary>
        /// User32 function to simulate a mouse event.
        /// </summary>
        /// <param name="dwFlags">
        /// The dw flags.
        /// </param>
        /// <param name="dx">
        /// The x position.
        /// </param>
        /// <param name="dy">
        /// The y position.
        /// </param>
        /// <param name="cButtons">
        /// The c buttons.
        /// </param>
        /// <param name="dwExtraInfo">
        /// The dw extra info.
        /// </param>
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);

        /// <summary>
        /// User32 function to get system metrics about various things.
        /// </summary>
        /// <param name="nIndex">
        /// The system metric or configurations to be retreived.
        /// </param>
        /// <returns>The system metrics.</returns>
        /// <see cref="http://msdn.microsoft.com/en-us/library/ms724385(VS.85).aspx"/>
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern int GetSystemMetrics(int nIndex);

        /// <summary>
        /// Swaps the mouse buttons.
        /// </summary>
        /// <param name="fSwap">
        /// If true, the right button becomes the primary button.
        /// </param>
        /// <returns>True if the swap was succesfully.
        /// </returns>
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool SwapMouseButton([param: MarshalAs(UnmanagedType.Bool)] bool fSwap);

        /// <summary>
        /// Makes the right mouse button the primary button.
        /// </summary>
        public static void MakeRightButtonPrimary()
        {
            SwapMouseButton(true);
        }

        /// <summary>
        /// Makes the left mouse button the primary button.
        /// </summary>
        public static void MakeLeftButtonPrimary()
        {
            SwapMouseButton(false);
        }

        /// <summary>
        /// Simulates a click with the left mouse button on the given position.
        /// </summary>
        /// <param name="x">
        /// The x position.
        /// </param>
        /// <param name="y">
        /// The y position.
        /// </param>
        public static void DoMouseLeftClick(int x, int y)
        {
            // Move the cursor into the position first
            System.Windows.Forms.Cursor.Position = new Point(x, y);
            if (GetSystemMetrics((int) SystemMetric.SM_SWAPBUTTON) != 0)
            {
                mouse_event((int) MouseEvent.RIGHT_DOWN | (int) MouseEvent.RIGHT_UP, x, y, 0, 0);
            }
            else
            {
                mouse_event((int) MouseEvent.LEFT_DOWN | (int) MouseEvent.LEFT_UP, x, y, 0, 0);
            }
        }

        /// <summary>
        /// Simulates a click with the right mouse button on the given position.
        /// </summary>
        /// <param name="x">
        /// The x position.
        /// </param>
        /// <param name="y">
        /// The y position.
        /// </param>
        public static void DoMouseRightClick(int x, int y)
        {
            // Move the cursor into the position first
            System.Windows.Forms.Cursor.Position = new Point(x, y);
            if (GetSystemMetrics((int) SystemMetric.SM_SWAPBUTTON) != 0)
            {
                mouse_event((int) MouseEvent.LEFT_DOWN | (int) MouseEvent.LEFT_UP, x, y, 0, 0);
            }
            else
            {
                mouse_event((int) MouseEvent.RIGHT_DOWN | (int) MouseEvent.RIGHT_UP, x, y, 0, 0);
            }
        }
    }
}